//*************************************************************************//
//*           _____   ____________            ______               __     *//
//*          / /__ \ / ____/ ____/           / ____/___  _________/ /     *//
//*     __  / /__/ // __/ / __/    ______   / /_  / __ \/ ___/ __  /      *//
//*    / /_/ // __// /___/ /___   /_____/  / __/ / /_/ / /  / /_/ /       *//
//*    \____//____/_____/_____/           /_/    \____/_/   \__,_/        *//
//*                                                                       *//
//*     Copyright (c) 2006 Ford Argentina. All Rights Reserved.           *//
//*                                                                       *//
//*************************************************************************//

package ar.com.ford.it.webengine.struts;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessages;
import ar.com.ford.it.webengine.persistence.PersistenceUtil;
import ar.com.ford.it.webengine.security.SessionController;
import ar.com.ford.it.webengine.security.SessionControllerFactory;
import ar.com.ford.it.webengine.settings.AppSettings;
import ar.com.ford.it.webengine.websession.WebSession;
import ar.com.ford.it.webengine.websession.WebSessionHelper;
import ar.com.ford.it.webengine.wslx.WslxUser;
import com.ford.it.logging.ILogger;
import com.ford.it.logging.Level;
import com.ford.it.logging.LogFactory;

/**
 * AbstractBaseAction <br>
 * 
 * Action base de la aplicacion web. <br>
 * Valida el request y autentica el usuario usando el RequestAuthProcessor configurado
 * para la aplicacion. <br>
 * Valida que el usuario tenga los permisos requeridos que se
 * hayan seteado en el parametro <b>privilege</b> del FordActionMapping. <br>
 * Si la sesion http es nueva, crea una nueva sesion interna y un nuevo WslxUser. <br>
 * Luego hace el dispatch al metodo configurado en el parametro <b>parameter</b>
 * (tambien en el FordActionMapping). <br>
 * La validacion puede llamar a los siguientes forwards, que deben definirse en 
 * el archivo <code>struts-config.xml</code>:
 * 
 *   <li> <b>application_error:</b> Error detectado en la aplicacion
 *   <li> <b>unregistered:</b> Usuario no tiene acceso a la aplicacion
 *   <li> <b>unauthorized:</b> Usuario no tiene permiso para ejecutar el action
 *   <li> <b>expired_session:</b> La sesion expiro
 * 
 * 
 * @author Aji
 * 
 */
public abstract class AbstractBaseAction extends DispatcherMethodAction {
	
    private static final String CLASS_NAME = AbstractBaseAction.class.getName();
    private static final ILogger log = LogFactory.getInstance().getLogger(CLASS_NAME);

	private static String NEW_LINE = System.getProperty("line.separator");
	

	/* (non-Javadoc)
	 * @see org.apache.struts.action.Action#execute(ActionMapping, ActionForm, HttpServletRequest, HttpServletResponse)
	 */
    public ActionForward execute(ActionMapping basemapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
        String METHOD_NAME = "execute";
		
		log.entering(CLASS_NAME, METHOD_NAME);
		
		FordActionMapping fordMapping = (FordActionMapping)basemapping;
		log.fine(NEW_LINE);
		log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "Action", fordMapping.getPath());

		ActionMessages errormsgs = new ActionMessages();
        ActionMessages msgs = new ActionMessages();
		ActionMessages warns = new ActionMessages();
		
		ActionForward result = null;
 
		
		SessionController sessionController = SessionControllerFactory.getInstance();
		WslxUser wslxuser = null;
		WebSession websession = null;

		HttpSession httpSession = request.getSession();
        boolean validated = false;

        if (httpSession == null) {
        	log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "No se pudo obtener httpsession");
        	return fordMapping.findForward(StrutsForwards.APPLICATION_ERROR);
        }

        try {
	        if (sessionController.isNewSession(request)) {
	        	log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Nueva Session");
	        	if (sessionController.isValidFirstRequest(request)) {
	        		log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "Nueva session - fisrt request autenticado - OK");
	        		
	        		WebSessionHelper webSessionHelper = new WebSessionHelper();
	        		websession = webSessionHelper.registerSession(request, sessionController.getUserId(request));
	        		
	        		if (websession == null) {
	        			log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "No se pudo crear websession");
	        			return fordMapping.findForward(StrutsForwards.APPLICATION_ERROR);
	        		}
	        		else {
	        			wslxuser = websession.getUser();
	        			sessionController.completeWslxLoad(wslxuser, request);
	        			
	        			if (sessionController.isLoggedUser(wslxuser, request)) {
	        				log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "nueva session - acceso validado - OK");
	        				
	        				if (sessionController.validateAccessToApp(wslxuser, request)) {
	        					log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "usuario autorizado");
	        					validated = true;
	        				}
	        				else {
	        					log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "usuario no autorizado");
	        					WebSessionHelper.removeWebSession(httpSession);
	        					result = fordMapping.findForward(StrutsForwards.SECURITY_UNAUTHORIZED);
	        				}
	        			}
						else {
	                    	log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "usuario no registrado");
	                    	WebSessionHelper.removeWebSession(httpSession);
	                    	result = fordMapping.findForward(StrutsForwards.SECURITY_UNREGISTERED);
						}
	        		}
	        	}
				else {
	            	log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "primer acceso invalido - faltan datos para registrar la sesion");
	            	result = fordMapping.findForward(StrutsForwards.SECURITY_UNREGISTERED);
				}
	        }
	        else {
	        	log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Session existente");
	        	
	        	websession = WebSessionHelper.getWebSession(request.getSession());
	        	if (sessionController.validateSession(request, websession)) {
	        		log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "session validada - Ok");
	        		
	        		wslxuser = websession.getUser();
	        		
	        		validated = true;
	        	}
	            else {
	            	log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "sesion expirada");
	            	WebSessionHelper.removeWebSession(httpSession);
	            	result = fordMapping.findForward(StrutsForwards.SECURITY_EXPIRED_SESSION);
	            }
	        }
	        
	  
	        if (validated) {
				/**
				 * Modificacion:
				 * Fecha: 01/08/2008
				 * Se modifico para que valide privilegio especifico, por accion de struts, contra
				 * los permisos que tiene el WslxUser cargados.
				 * 
				 * Anterior:
				 * Al parecer validaba a partir del path del action de struts, busca este string
				 * en un hashmap en app, cargado a partir de los items del menu...
				 * if (sessionController.validateActionAccess(wslxuser, fordMapping.getPath())) {
				 */
				if (sessionController.validateActionAccessByPrivilege(wslxuser, fordMapping.getPrivilege())) {
					try {
						result = executeAction(fordMapping, form, request, response, websession, msgs, warns, errormsgs);
					}
						catch (Exception exc) {
						log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "Exception: ", exc);
					}
				}
				else {
					result = fordMapping.findForward(StrutsForwards.SECURITY_UNAUTHORIZED);
				}
	        }
	
	        if (!msgs.isEmpty()) 
	        	super.saveMessages(request, msgs);
	        
			// warnings
			if (!warns.isEmpty())
				request.setAttribute("warningMessages", warns);
	
	        if (!errormsgs.isEmpty())
	        	super.saveErrors(request,errormsgs);
        }
        catch (Exception e) {
        	log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "UnhandledException", e);
        	if (AppSettings.getInstance().isFjf_persistence_facilities()) {
            	try {
            		log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "RollBack Transacciones acticas");
            		PersistenceUtil.commitTransaction();
            	}
            	catch (Exception pe) {
            		log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "RollBack Transaction Exception", pe);
    			}
        	}
        	result = fordMapping.findForward(StrutsForwards.APPLICATION_ERROR);
		}

        if (AppSettings.getInstance().isFjf_persistence_facilities()) {
        	log.logp(Level.FINE, CLASS_NAME, METHOD_NAME, "Close Persistence Manager");
        	try {
        		PersistenceUtil.closePersistenceManager();
        	}
        	catch (Exception pe) {
        		log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "Close Persistence Manager Exception", pe);
			}
        }
        
		log.exiting(CLASS_NAME, METHOD_NAME, result);        	
        return result;
    }

    /**
     * Accion commun a todas las aquellas pantallas que requieran paginacion via displaytag
     * 
     * @param mapping
     * @param form
     * @param request
     * @param response
     * @param websession
     * @param msgs
     * @param warns
     * @param errormsgs
     * @return forwarding
     */
	public ActionForward doPaginate(FordActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, WebSession websession, ActionMessages msgs, ActionMessages warns, ActionMessages errormsgs) {
		return mapping.findForward("success");
	}

}